package logic

import (
	"errors"
	"fmt"
	"net/url"
	"os"
	"path"
	"path/filepath"
	"strings"

	"gddgame.cc/galaxy/common/feature/phantom"
	"gddgame.cc/galaxy/utils"
)

type UnitContainer interface {
	Start() error
	Stop() error
	Find() bool
	Clean() error
	Watch() map[string]interface{}
	Analyse(info *UnitInfo) error
}

var (
	platformInstance phantom.Platform
	configInstance   *Config
	db               *DB
)

func Init(config *Config, platform phantom.Platform, cmd bool) error {
	var err error
	if err := config.Init(); err != nil {
		return err
	}

	// 初始化本地数据库
	db, err = InitDatabase(config.Database, cmd)
	if err != nil {
		return err
	}

	platformInstance = platform
	configInstance = config
	return nil
}
func Database() *DB {
	return db
}

// schema是文件地址，支持file和cloud
// Query是启动时的环境变量：参数符合Get标准
// Fragment是启动时的运行参数: 包含command和args
// 本地目录或文件
// file:///path/file?a=1&b=2#-pa|-a=123
// cloud为当前所在数据中心的云服务存储，需要将文件先下载，在进行分析
// cloud:///path/file?a=1

func ValidTarget(target string) (*url.URL, map[string]string, error) {
	u, err := url.Parse(target)
	if err != nil {
		return nil, nil, err
	}
	file := u.Path
	q := make(map[string]string)
	if u.Scheme == "cloud" {
		// 集群，云服务存储
		// 判断云端文件是否存在
	} else if u.Scheme == "file" {
		// 本地
		if !utils.IsExist(file) {
			return nil, nil, fmt.Errorf("Target is Error: %s", u.String())
		}
	} else {
		return nil, nil, errors.New("Schema not support: file, cloud")
	}

	if err := utils.ParseQuery(q, u.RawQuery); err != nil {
		return nil, nil, err
	}
	return u, q, nil
}
func Analyse(unit *Unit, u *url.URL, q map[string]string, force bool) error {
	info := UnitInfo{}
	unitPath := configInstance.WorkPath + "/" + unit.Name
	file := u.Path
	if u.Scheme == "cloud" {
		// 集群，云服务存储
		file = unitPath + "/" + path.Base(file)
		if utils.IsExist(file) {
			if !force {
				return errors.New("target exist, can force to remove")
			}
			if err := os.RemoveAll(info.WorkDir); err != nil {
				return err
			}
		}
		// 下载文件
		info.IsDownload = true
	}
	info.Args = u.Fragment
	info.Env = q
	info.IsOrigin = true
	if !strings.HasSuffix(file, "/") {
		// 是一个文件
		ext := path.Ext(file)
		// 判断是否需要解压
		if ext == "tar" || ext == "tar.gz" || ext == "zip" {
			// 建立工作目录
			info.WorkDir = unitPath + "/" + filepath.Base(file)
			if utils.IsExist(info.WorkDir) {
				if !force {
					return errors.New("workDir exist, can force to remove")
				}
				if err := os.RemoveAll(info.WorkDir); err != nil {
					return err
				}
			}
			if err := decompression(file, info.WorkDir); err != nil {
				return err
			}
			info.IsOrigin = false
		} else {
			// 单个文件执行
			info.WorkDir = path.Dir(file)
			info.Command = "./" + path.Base(file)
		}
	} else {
		info.WorkDir = file
	}
	// 判断项目类型
	if utils.IsExist(info.WorkDir + "/Dockerfile") {
		// 是Docker类型项目
		unit.Type = DockerType
	} else {
		unit.Type = ProcessType
	}

	container := unit.Container()
	if err := container.Analyse(&info); err != nil {
		return err
	}

	if !info.IsOrigin && info.IsDownload {
		// 删除下载的压缩文件
		_ = os.Remove(file)
	}
	unit.Info = info
	return nil
}

func GenerateLog(unit *Unit) (*inlineLog, error) {
	log := &inlineLog{}
	if err := log.bindFile(configInstance.LogPath + unit.Name + "/" + configInstance.LogFormat); err != nil {
		return nil, err
	}
	return log, nil
}

func AllowRecover(unit *Unit) bool {
	if unit.RecoverNumber > configInstance.MaxRecover {
		return false
	}
	return true
}

func GetWorkDir(unit *Unit) string {
	workDir := unit.Info.WorkDir
	if !unit.Info.IsOrigin {
		// 内部目录，隐藏全局工作路径
		workDir = strings.Replace(workDir, configInstance.WorkPath+"/", "", 1)
	}
	return workDir
}
